<script>
import T from "ant-design-vue/es/table/Table";
import Vue from 'vue';
export default {
  name: "CustomTable",
  props: Object.assign({}, T.props, {
    showAlert: {
      type: Boolean,
      default: true
    },
    showPagination: {
      type: Boolean,
      default: true
    },
    showSelection: {
      type: Boolean,
      default: true
    },
    // 是否显示自定义列设置
    showColSettings: {
      type: Boolean,
      default: false
    },
    selectionType: {
      type: String,
      default: 'checkbox'
    },
    rowKey: {
      type: String,
      default: "id"
    },
    dataSource: {
      type: [Object, Array],
      required: true,
      default() {
        return {
          total: 0,
          current: 1,
          size: 10,
          records: []
        };
      }
    },
    hideColumns: {
      type: Array,
      default() {
        return []
      }
    },
    // 不进行自定义列设置的字段，dataIndex或者key值
    hideColSettings: {
      type: Array,
      default() {
        return []
      }
    },
    // 初始化自定义列关闭状态的字段，dataIndex或者key值
    defaultCloseColSettings: {
      type: Array,
      default() {
        return []
      }
    },
    onChange: {
      type: Function,
      default: null
    },
    onRowClick: {
      type: Function,
      default: null
    },
    // 指定每页可以显示多少条
    pageSizeOptions: {
      type: Array,
      default() {
        return ['10', '20', '30', '40']
      }
    }
  }),
  data() {
    return {
      selectedRows: [],
      selectedRowKeys: [],
      settingColumns: [],
      colSearchValue: null
    };
  },
  computed: {
    pageInfo() {
      return {
        showSizeChanger: true,
        showQuickJumper: true,
        pageSizeOptions: this.pageSizeOptions,
        total: Number(this.dataSource.total) || 0,
        showTotal: total => `共 ${total} 条`,
        current:
          Number(this.dataSource.currentPage || this.dataSource.current) || 1,
        pageSize: Number(this.dataSource.pageSize || this.dataSource.size) || 10
      };
    },
    customColumns: state => {
      if (state.hideColumns && state.hideColumns.length > 0) {
        return state.columns.filter(item => {
          if (item.dataIndex) {
            return !state.hideColumns.includes(item.dataIndex);
          } else if (item.title) {
            return !state.hideColumns.includes(item.title);
          } else {
            return true;
          }
        });
      } else {
        return state.columns;
      }
    },
    customColcolumns() {
      const cols = this.customColumns.filter(item => {
        if(this.hideColSettings.includes(item.dataIndex) || this.hideColSettings.includes(item.key)) {
          return true;
        }
        if (this.settingColumns.includes(item.dataIndex)) {
          return true;
        }
        return false;
      })
      if (this.showColSettings) {
        return cols;
      } else {
        return this.customColumns;
      }
    }
  },
  watch: {
    customColumns: {
      immediate: true,
      handler(val) {
        if (val) {
          // 初始化列设置
          const key = this.$route.name+":ColSettings";
          let colSettings= Vue.ls.get(key.toUpperCase());
          if (colSettings==null||colSettings==undefined) {
            let allSettingColumns = [];
            this.customColumns.forEach(item => {
              if(!this.defaultCloseColSettings.includes(item.dataIndex)) {
                allSettingColumns.push(item.dataIndex);
              }
            })
            this.settingColumns = allSettingColumns;
          } else{
            this.settingColumns = colSettings;
          }
        }
      }
    }
  },
  methods: {
    getSelectedRowKeys() {
      return this.selectedRowKeys;
    },
    getSelectedRows() {
      return this.selectedRows;
    },
    onClearRowKeys() {
      // 清空选中内容
      this.selectedRowKeys = [];
      this.selectedRows = [];
      this.$emit("selectedRow", this.selectedRowKeys);
    },
    onSelectChange(selectedRowKeys, selectedRows) {
      
      // 选中内容
      this.selectedRowKeys = selectedRowKeys;
      if (this.rowKey) {
        // 分页数据选择selectedRows只返回当前页的数据，需要特殊处理。1合并数据，2过滤出已选中的数据，3去重
        let map = new Map();
        this.selectedRows = [...this.selectedRows, ...selectedRows]
          .filter(item => this.selectedRowKeys.includes(item[this.rowKey]))
          .reduce((item, next) => {
            if (!map.has(next[this.rowKey])) {
              map.set(next[this.rowKey], true);
              item.push(next);
            }
            return item;
          }, []);
      }
      this.$emit("selectedRowKey", this.selectedRowKeys);
      this.$emit("selectedRow", this.selectedRows);
    },
    onSelect(record, selected, selectedRows, nativeEvent) {
      this.$emit('rowSelect', record,selected, selectedRows)
    },
    onTableChange(pagination, filters, sorter) {
      // 表格分页、过滤、排序变化的时候触发change回调
      const query = {
        currentPage: pagination.current,
        pageSize: pagination.pageSize,
        sortField: sorter.field,
        sortOrder: sorter.order,
        ...filters
      };
      this.onChange && this.onChange(query);
      this.$emit("change", query);
    },
    onCustomRow(record) {
      return {
        on: {
          click: e => {
            e.preventDefault();
            this.onRowClick && this.onRowClick(record);
            this.$emit("rowClick", record);
          }
        }
      };
    },
    // 列设置更改事件
    onColSettingsChange(checkedValues) {
      const key = this.$route.name+":ColSettings";
      Vue.ls.set(key.toUpperCase(), checkedValues, 7 * 24 * 60 * 60 * 1000)
      this.settingColumns = checkedValues;
    },
    renderAlert() {
      // 绘制统计列数据
      return (
        <a-alert class="table-alert">
          <div slot="message" class="table-alert-info">
            <div class="table-alert-info-content">
              <span style="margin-right: 12px">
                已选择{" "}
                <a style="font-weight: 600">{this.selectedRowKeys.length}</a> 项
              </span>
            </div>
            {this.selectedRowKeys.length > 0 && (
              <div class="table-alert-info-option">
                <a onClick={this.onClearRowKeys}>清空</a>
              </div>
            )}
          </div>
        </a-alert>
      );
    },
    renderSettingColumns() {
      // 自定义列，可通过插槽自定义配置模板
      // 如：
      // <template v-slot:colSettings>
      //  <a-button class="table-custom-cols">
      //    <a-icon type="setting" />设置
      //  </a-button>
      // </template>
      return (
        <a-popover title="自定义列" trigger="click" placement="leftBottom">
          <template slot="content">
            <a-checkbox-group v-model={this.settingColumns} defaultValue={this.settingColumns} on-change={this.onColSettingsChange}>
              <a-input-search placeholder="搜索字段" v-model={this.colSearchValue} />
              <a-row style="width: 400px;margin-top:6px;">
                {this.customColumns.map(item => {
                  const title = item.slots && item.slots.title? item.columnTitle:item.title
                  if(!this.hideColSettings.includes(item.dataIndex) && !this.hideColSettings.includes(item.key)) {
                    return (
                      <a-col span={12} class={{'curCol':this.colSearchValue && title.indexOf(this.colSearchValue) > -1}}>
                        <a-checkbox value={item.dataIndex}>
                          <j-ellipsis value={title} length={22} />
                        </a-checkbox>
                      </a-col>
                    )
                  }
                })}
              </a-row>
            </a-checkbox-group>
          </template>
          {this.$slots.colSettings?
            this.$slots.colSettings
            : <a-button class="table-custom-cols">
              <a-icon type="setting" />字段配置
            </a-button>
          }
        </a-popover>
      )
    }
  },
  render() {
    const {
      showAlert,
      showColSettings,
      showPagination,
      showSelection,
      dataSource,
      onTableChange,
      pageInfo
    } = this;
    const rowSelection = {
      selectedRowKeys: this.selectedRowKeys,
      onChange: this.onSelectChange,
      type: this.selectionType,
      onSelect: this.onSelect
    };
    let props = {};
    Object.keys(T.props).forEach(key => {
      if (key === "dataSource") {
        props[key] =
          dataSource instanceof Array ? dataSource : dataSource.records;
      } else if (key === "rowSelection") {
        // props[key] = showSelection ? rowSelection : null;
        props[key] = showSelection ? Object.assign(rowSelection, this[key]) : null;
      } else if (key === "pagination") {
        props[key] =
          showPagination && !(dataSource instanceof Array) ? Object.assign(pageInfo, this[key]) : false;
      } else if (key === "customRow") {
        props[key] = this[key] || this.onCustomRow;
      } else if (key === "columns") {
        props[key] = this.customColcolumns;
      } else {
        this[key] && (props[key] = this[key]);
      }
    });
    return (
      <div class="table">
        { showAlert && showColSettings?
          <div class="table-handle">{this.renderAlert()} {this.renderSettingColumns()}</div>
          : showAlert && !showColSettings? <div class="table-handle"> {this.renderAlert()}</div>
          : !showAlert && showColSettings? <div class="table-handle"> {this.renderSettingColumns()}</div>: null
        }
        <a-table
          {...{ props, scopedSlots: { ...this.$scopedSlots } }}
          onChange={onTableChange}
        >
          {Object.keys(this.$slots).map(name => (
            <template slot={name}>{this.$slots[name]}</template>
          ))}
        </a-table>
      </div>
    );
  }
};
</script>

<style scoped lang="less">
.table {
  position: relative;
  .table-alert {
    margin-bottom: 16px;
    .table-alert-info {
      display: flex;
      .table-alert-info-content {
        flex: 1 1;
      }
      .table-alert-info-option {
        min-width: 48px;
        padding-left: 16px;
      }
    }
    button[role="switch"] * {
      z-index: 999;
    }
  }
  /deep/.ant-table {
    .ant-table-body {
      overflow-x: auto !important;
    }
  }
  .table-custom-cols {
    position: absolute;
    right: 0;
    top: -40px;
    z-index: 8;
  }
}
/deep/.curCol {
  label{
    color: #1890ff;
  }
}
</style>
